#include "shuttle.h"

extern int G_W, G_H;

Shuttle::Shuttle(SCENE *scene, QTimeLine *global_tl, CASH *cash, HUD *hud):QObject(), QGraphicsItemGroup()
{

    this->setData(777,"Shuttle");

    this->setObjectName("Shuttle");

    this->cash=cash;

    str_state = "shuttle";
    cannons_state = true;

    this->scene=scene;

    this->hud = hud;

    point = 100;

    border = cash->cash_poly->value("Res/Ships/Shuttle/ship.poly");

    shield_border = cash->cash_poly->value("Res/Ships/Shuttle/shield.poly");

    init();

    collisia_control = new COLLISIA_CONTROL(scene,((QGraphicsObject*)this), this,global_tl,cash,10);

    timer_id=startTimer(5000);  // Автофокус на шатл

    connect(this, SIGNAL(signal_keys_pressed()), SLOT(slot_shuttle_fly()));
    connect(this, SIGNAL(signal_keys_released()), SLOT(slot_shuttle_fly_released()));

    connect(tl_anim_ship, SIGNAL(valueChanged(qreal)), this, SLOT(slot_tl_changed()));

    connect(this, SIGNAL(signal_keys_pressed()), SLOT(slot_fire_start()));
    connect(this, SIGNAL(signal_keys_released()), SLOT(slot_fire_end()));

    connect(collisia_control,SIGNAL(Collisia(QPointF,int)),SLOT(Damage_Detected(QPointF,int)));

//connect sprite shuttle base
    connect(this, SIGNAL(signal_fly(MOVE_DIRECTION)), sprite_ship, SLOT(slot_fly(MOVE_DIRECTION)));
    connect(this, SIGNAL(signal_fly_finish(MOVE_DIRECTION)), sprite_ship, SLOT(slot_fly_finish(MOVE_DIRECTION)));

    connect(this, SIGNAL(signal_transform(QString,QString)), sprite_ship, SLOT(slot_transform(QString,QString)));

//gamepad init
    gamepad = new SDL_GAMEPAD(this);
    gamepad->start();

    qRegisterMetaType<GAMEPAD_ACTION>("GAMEPAD_ACTION");

    connect(gamepad, SIGNAL(signal_gamepad_clicked(GAMEPAD_ACTION)), this, SLOT(slot_gamepad_clicked(GAMEPAD_ACTION)));
    connect(gamepad, SIGNAL(signal_gamepad_released(GAMEPAD_ACTION)), this, SLOT(slot_gamepad_released(GAMEPAD_ACTION)));

}

void Shuttle::init()
{
    this->setFlag(ItemIsFocusable, true);

    sound_fireboll = new SOUND_POWER(cash,"Res/Sound/Shuttle/fireboll.ogg",this);
    gun = new SOUND_POWER(cash,"Res/Sound/Shuttle/gun.ogg",this);
    damage_sound = new SOUND_POWER(cash,"Res/Sound/Shuttle/shield off.ogg",this);

    sprite_ship = new SPRITE_SHIP_BASE(cash, this);
    sprite_ship->start();

    item_gatling_1 = new GRAPHICS_PIXMAP_ITEM(*cash->cash_pixmap->value(DEF_SHIPS_PATH + "Shuttle/gatling.png"), this);
    item_gatling_2 = new GRAPHICS_PIXMAP_ITEM(*cash->cash_pixmap->value(DEF_SHIPS_PATH + "Shuttle/gatling.png"), this);

    item_cannon_1 = new GRAPHICS_PIXMAP_ITEM(QPixmap(), this);
    item_cannon_2 = new GRAPHICS_PIXMAP_ITEM(QPixmap(), this);

    set_keys = new QSet<int>();

    last_key = 0;

    shield = new SHUTTLE_SHIELD(cash);
    this->addToGroup(shield);
    shield->setZValue(10);

    shield->setPos(- 26, -13);

    align();
    anim_init();
}

//функция инициализации анимации
void Shuttle::anim_init()
{
    init_anim_fly();
    init_anim_gatling();
    init_anim_cannon();
}

//функция расставляет все элементы на корабле
void Shuttle::align()
{
    //ставим пушки на свои места
    item_gatling_1->setPos(75, 75);
    item_gatling_2->setPos(118, 75);

    item_cannon_1->setPos(40, 90);
    item_cannon_2->setPos(122, 90);

    //добавляем все барахло в группу

    this->addToGroup(item_gatling_1);
    this->addToGroup(item_gatling_2);

    this->addToGroup(item_cannon_1);
    this->addToGroup(item_cannon_2);

    //выставляем кто под кем
    sprite_ship->setZValue(0.5);

    item_gatling_1->setZValue(1);
    item_gatling_2->setZValue(1);

    item_cannon_1->setZValue(0);
    item_cannon_2->setZValue(0);
}

//фукнция выводит в дебаг все нажатые в данный кнопки
void Shuttle::debug_set_keys()
{
    qDebug() << "Set Keys";
    foreach(int i, *set_keys){
        qDebug() << i;
    }
}

//функция возвращает массив с нажатыми в текущий момент кнопками
QSet<int> *Shuttle::get_set_keys()
{
    return this->set_keys;
}

void Shuttle::timerEvent(QTimerEvent *)
{

    if(!this->hasFocus()) this->setFlag(ItemIsFocusable, true);

}

void Shuttle::keyPressEvent(QKeyEvent *event)
{
    if(event->isAutoRepeat())
        return;

    if(event->key() == Qt::Key_J){
        emit signal_fire_start(GATLING);

    }

    if(event->key() == Qt::Key_K && cannons_state){
        emit signal_fire_start(CANNON);

    }

    if(event->key() == Qt::Key_L)
        emit signal_fire_start(ROCKET);


    if(event->key() == Qt::Key_U){
        fly_step = 20;
        slot_transform_to_shuttle();
        hud->set_shuttle_type(2);
    }

    if(event->key() == Qt::Key_I){
        fly_step = 15;
        slot_transform_to_speedboat();
        hud->set_shuttle_type(1);
    }

    if(event->key() == Qt::Key_O){
        fly_step = 25;
        slot_transform_to_submarine();
        hud->set_shuttle_type(3);
    }

    set_keys->insert(event->key());
    emit signal_keys_pressed();
}

void Shuttle::keyReleaseEvent(QKeyEvent *event)
{
    if(event->isAutoRepeat())
        return;

    if(event->key() == Qt::Key_J)
        emit signal_fire_finish(GATLING);

    if(event->key() == Qt::Key_K){
        emit signal_fire_finish(CANNON);
    }

    set_keys->remove(event->key());
    emit signal_keys_released();

    if(event->key() == Qt::Key_A || event->key() == Qt::Key_D)
        emit signal_fly_finish();

    if(event->key() == Qt::Key_A)
        emit signal_fly_finish(LEFT);

    if(event->key() == Qt::Key_D)
        emit signal_fly_finish(RIGHT);

    if(event->key() == Qt::Key_W)
        emit signal_fly_finish(TOP);

    if(event->key() == Qt::Key_S)
        emit signal_fly_finish(DOWN);
}

void Shuttle::init_anim_fly()
{
//перемещение корабля
    tl_anim_ship = new QTimeLine(500, this);

    tl_anim_ship->setLoopCount(0);
    tl_anim_ship->setFrameRange(0, 100);

    dx = dy = 0;
    flag_tl_started = false;
    fly_step = 20;
}

void Shuttle::init_anim_gatling()
{
    time_line_gatlings = new QTimeLine(50, this);

    anim_gatling_1 = new QGraphicsItemAnimation(this);
    anim_gatling_2 = new QGraphicsItemAnimation(this);

    anim_gatling_1->setItem(item_gatling_1);
    anim_gatling_1->setTimeLine(time_line_gatlings);

    anim_gatling_2->setItem(item_gatling_2);
    anim_gatling_2->setTimeLine(time_line_gatlings);

    time_line_gatlings->setFrameRange(0, 1);
    time_line_gatlings->setLoopCount(0);

    anim_gatling_1->setPosAt(0, item_gatling_1->pos());
    anim_gatling_1->setPosAt(0.5, QPointF(item_gatling_1->pos().x(), item_gatling_1->pos().y() + 10));
    anim_gatling_1->setPosAt(1, item_gatling_1->pos());

    anim_gatling_2->setPosAt(0, item_gatling_2->pos());
    anim_gatling_2->setPosAt(0.5, QPointF(item_gatling_2->pos().x(), item_gatling_2->pos().y() + 10));
    anim_gatling_2->setPosAt(1, item_gatling_2->pos());

    flag_anim_gatling = false;
}

void Shuttle::init_anim_cannon()
{
    time_line_cannons = new QTimeLine(350, this);

    anim_cannon_1 = new QGraphicsItemAnimation(this);
    anim_cannon_2 = new QGraphicsItemAnimation(this);

    anim_cannon_1->setItem(item_cannon_1);
    anim_cannon_1->setTimeLine(time_line_cannons);

    anim_cannon_2->setItem(item_cannon_2);
    anim_cannon_2->setTimeLine(time_line_cannons);

    time_line_cannons->setFrameRange(0, 1);
    time_line_cannons->setLoopCount(0);

    anim_cannon_1->setPosAt(0, item_cannon_1->pos());
    anim_cannon_1->setPosAt(0.4, QPointF(item_cannon_1->pos().x(), item_cannon_1->pos().y() + 30));
    anim_cannon_1->setPosAt(1, item_cannon_1->pos());

    anim_cannon_2->setPosAt(0, item_cannon_2->pos());
    anim_cannon_2->setPosAt(0.4, QPointF(item_cannon_2->pos().x(), item_cannon_2->pos().y() + 30));
    anim_cannon_2->setPosAt(1, item_cannon_2->pos());

    flag_anim_cannon = false;
}

QRectF Shuttle::boundingRect() const
{
    return sprite_ship->boundingRect();
}

QPainterPath Shuttle::shape() const
{
    return *border;
}

int Shuttle::type() const
{
    return point;
}

void Shuttle::set_points(int value)
{
    this->point = value;
}

void Shuttle::cannons_visible(bool value)
{
    item_cannon_1->setVisible(value);
    item_cannon_2->setVisible(value);
}

bool Shuttle::Get_Cannons_State()
{
    return cannons_state;
}

Shuttle::~Shuttle(){}

//слоты анимации полета корабля
void Shuttle::slot_shuttle_fly()
{
    if(set_keys->contains(Qt::Key_A) ||
       set_keys->contains(Qt::Key_D) ||
       set_keys->contains(Qt::Key_W) ||
       set_keys->contains(Qt::Key_S)){
        if(!flag_tl_started){
            tl_anim_ship->start();
            flag_tl_started = true;
        }
    }

    foreach (int key, *set_keys)
        switch (key) {
            case Qt::Key_A:
                dx = - fly_step;
                last_key = Qt::Key_A;
                emit signal_fly(LEFT);
            break;

            case Qt::Key_D:
                dx = fly_step;
                last_key = Qt::Key_D;
                emit signal_fly(RIGHT);
            break;

            case Qt::Key_W:
                dy = - fly_step;
                last_key = Qt::Key_W;
                emit signal_fly(TOP);
            break;

            case Qt::Key_S:
                dy = fly_step;
                last_key = Qt::Key_S;
                emit signal_fly(DOWN);
            break;
        }

    if(set_keys->contains(Qt::Key_A) && set_keys->contains(Qt::Key_D)){
        dx = 0;
    }

    if(set_keys->contains(Qt::Key_W) && set_keys->contains(Qt::Key_S)){
        dy = 0;
    }

}

void Shuttle::slot_shuttle_fly_released()
{
    switch (last_key) {
        case Qt::Key_A:
            dy = 0;
            dx = - fly_step;
        break;

        case Qt::Key_D:
            dy = 0;
            dx = fly_step;
        break;

        case Qt::Key_W:
            dy = - fly_step;
            dx = 0;
        break;

        case Qt::Key_S:
            dy = fly_step;
            dx = 0;
        break;

        default:
            dx = 0;
            dy = 0;
    }

    if(!set_keys->contains(Qt::Key_A) &&
       !set_keys->contains(Qt::Key_D) &&
       !set_keys->contains(Qt::Key_W) &&
       !set_keys->contains(Qt::Key_S)){
        if(flag_tl_started){
            dx = dy = 0;
            slot_tl_changed();
            tl_anim_ship->stop();
            flag_tl_started = false;
        }
    }

}

void Shuttle::slot_tl_changed()
{
    if(this->pos().x() + dx < 0)
        dx = 0;

    if(this->pos().x() + this->boundingRect().width() + dx > G_W)
        dx = 0;

    if(this->pos().y() + dy < 0)
        dy = 0;

    if(this->pos().y() + this->boundingRect().height() + dy > G_H)
        dy = 0;

    this->setPos(this->pos().x() + dx, this->pos().y() + dy);
}

//слоты анимации оружия
void Shuttle::slot_fire_start()
{
    if(set_keys->contains(Qt::Key_J) && !flag_anim_gatling){
        time_line_gatlings->start();
        flag_anim_gatling = true;
        time_line_gatlings->setLoopCount(0);

        //перенес гатлинг сюда
        gun->Play_Now();
        }

    if(set_keys->contains(Qt::Key_K) && !flag_anim_cannon){
        time_line_cannons->start();
        flag_anim_cannon = true;
        time_line_cannons->setLoopCount(0);

        //перенес файрболл сюда
        sound_fireboll->Play_Now();

    }
}

void Shuttle::slot_fire_end()
{
    if(!set_keys->contains(Qt::Key_J) && flag_anim_gatling){
        time_line_gatlings->setLoopCount(1);
        connect(anim_gatling_1->timeLine(), SIGNAL(finished()), this, SLOT(slot_gatling_released()));

    }

    if(!set_keys->contains(Qt::Key_K) && flag_anim_cannon){
        time_line_cannons->setLoopCount(1);
        connect(anim_cannon_1->timeLine(), SIGNAL(finished()), this, SLOT(slot_cannon_released()));

    }
}

void Shuttle::Damage_Detected(QPointF a, int d)
{

    if(str_state.contains("speedboat"))
        d/=2;

    point-=d;

    hud->set_points(point/10);

    if(point > 50){
        shield->damaged(a);
    }
    else
        damage_sound->Play_Now();

    if(point<=0){
        emit Uuuups_I_die();
        this->scene->removeItem(this);
    }

}

void Shuttle::simulate_damage()
{
    qDebug() << mapToScene(QPointF(80, 20));
    Damage_Detected(mapToScene(QPointF(80, 20)), 10);
}

void Shuttle::start_mission_anim()
{
    QGraphicsItemAnimation *anim = new QGraphicsItemAnimation(this);
    anim->setItem(this);
    anim->setTimeLine(new QTimeLine(1500));
    anim->timeLine()->setEasingCurve(QEasingCurve::Type(7));

    anim->setPosAt(1, QPointF(G_W/2 - this->boundingRect().width()/2, G_H - this->boundingRect().height() - 50));
    anim->setPosAt(0, anim->posAt(1) + QPointF(0, G_H*2));

    anim->timeLine()->start();
}

void Shuttle::slot_fake_start_left()
{
    QGraphicsItemAnimation *anim = new QGraphicsItemAnimation(this);
    anim->setItem(this);
    anim->setTimeLine(new QTimeLine(1800));
    anim->timeLine()->setEasingCurve(QEasingCurve::Type(7));

    anim->setPosAt(1, QPointF(153, 201));
    anim->setPosAt(0, anim->posAt(1) - QPointF(G_W*2, 0));

    anim->timeLine()->start();
}

void Shuttle::slot_fake_start_right()
{
    QGraphicsItemAnimation *anim = new QGraphicsItemAnimation(this);
    anim->setItem(this);
    anim->setTimeLine(new QTimeLine(1800));
    anim->timeLine()->setEasingCurve(QEasingCurve::Type(7));

    anim->setPosAt(1, QPointF(996, 201));
    anim->setPosAt(0, anim->posAt(1) + QPointF(G_W*2, 0));

    anim->timeLine()->start();
}

void Shuttle::slot_gamepad_clicked(GAMEPAD_ACTION action)
{
    switch (action) {
    case J_LEFT:
        set_keys->insert(Qt::Key_A);
        break;

    case J_RIGHT:
        set_keys->insert(Qt::Key_D);
        break;

    case J_TOP:
        set_keys->insert(Qt::Key_W);
        break;

    case J_DOWN:
        set_keys->insert(Qt::Key_S);
        break;

    case J_GATLING:
        gun->Play_Now();
        emit signal_fire_start(GATLING);
        break;

    case J_CANNON:
        sound_fireboll->Play_Now();
        emit signal_fire_start(CANNON);
        break;

    case J_SHUTTLE:
        fly_step = 20;
        slot_transform_to_shuttle();
        hud->set_shuttle_type(2);
        break;

    case J_SPEEDBOAT:
        fly_step = 15;
        slot_transform_to_speedboat();
        hud->set_shuttle_type(1);
        break;

    case J_SUBMARINE:
        fly_step = 25;
        slot_transform_to_submarine();
        hud->set_shuttle_type(3);
        break;

    default:
        break;
    }

    emit signal_keys_pressed();
}

void Shuttle::slot_gamepad_released(GAMEPAD_ACTION action)
{
    switch (action) {
    case J_GATLING:
        emit signal_fire_finish(GATLING);
        break;

    case J_CANNON:
        emit signal_fire_finish(CANNON);
        break;

    case J_LEFT:
        emit signal_fly_finish(LEFT);
        emit signal_fly_finish();
        break;

    case J_RIGHT:
        emit signal_fly_finish(RIGHT);
        emit signal_fly_finish();
        break;

    default:
        break;
    }

    set_keys->clear();
    emit signal_keys_released();
}

void Shuttle::slot_transform_to_speedboat()
{
    emit signal_transform(str_state, "speedboat");
    str_state = "speedboat";
    cannons_state = false;
    cannons_visible(false);
}

void Shuttle::slot_gatling_released()
{

    flag_anim_gatling = false;
    disconnect(anim_gatling_1->timeLine(), SIGNAL(finished()), this, SLOT(slot_gatling_released()));

}

void Shuttle::slot_cannon_released()
{
    flag_anim_cannon = false;
    disconnect(anim_cannon_1->timeLine(), SIGNAL(finished()), this, SLOT(slot_cannon_released()));
}



void Shuttle::slot_transform_to_shuttle()
{
    emit signal_transform(str_state, "shuttle");
    str_state = "shuttle";
    cannons_state = true;
    cannons_visible(true);
}

void Shuttle::slot_transform_to_submarine()
{
    emit signal_transform(str_state, "submarine");
    str_state = "submarine";
    cannons_state = true;
    cannons_visible(true);
}
